package cn.ronghui.project.infrastructure.adapter.repository;

import cn.ronghui.project.domain.application.adapter.repository.IApplicationRepository;
import cn.ronghui.project.domain.application.model.entity.*;
import cn.ronghui.project.infrastructure.dao.IAllocationDao;
import cn.ronghui.project.infrastructure.dao.IApplicationDao;
import cn.ronghui.project.infrastructure.dao.IRoomDao;
import cn.ronghui.project.infrastructure.dao.IStudentDao;
import cn.ronghui.project.infrastructure.dao.po.Allocation;
import cn.ronghui.project.infrastructure.dao.po.Application;
import cn.ronghui.project.infrastructure.dao.po.Room;
import cn.ronghui.project.infrastructure.dao.po.Student;
import cn.ronghui.project.types.enums.AllocationStatusEnumVO;
import cn.ronghui.project.types.enums.AppliStatusEnumVO;
import cn.ronghui.project.types.enums.RoomStatusEnumVO;
import cn.ronghui.project.types.enums.RoomTypeEnumVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;

@Repository
@Slf4j
public class ApplicationRepository implements IApplicationRepository {

    @Resource
    private IAllocationDao allocationDao;

    @Resource
    private IRoomDao roomDao;

    @Resource
    private IApplicationDao applicationDao;

    @Resource
    private IStudentDao studentDao;

    @Override
    public ApplicationEntity queryApplicationInfo(String studentId) {
        // 查询studentId并且状态为待审核
        Application application = applicationDao.queryApplicationInfoByStuIdAndStatus(studentId);
        if(application == null){
            log.info("申请信息不存在，创建申请表，studentId:{}",studentId);
            return null;
        }
        return ApplicationEntity.builder()
                .applicationId(application.getApplicationId())
                .studentId(application.getStudentId())
                .roomType(RoomTypeEnumVO.getRoomStatusEnumVO(application.getRoomType()))
                .status(AppliStatusEnumVO.getAppliStatusEnum(application.getStatus()))
                .startDate(application.getStartDate())
                .endDate(application.getEndDate())
                .build();
    }

    @Override
    public AllocationEntity checkAllocationByStudentId(String studentId) {
        Allocation allocationReq = new Allocation();
        allocationReq.setStudentId(studentId);
        allocationReq.setStatus(AllocationStatusEnumVO.ASSIGNED.getInfo());
        Allocation allocationResp = allocationDao.queryAllocationInfoByStudentIdAndStatus(allocationReq);
        if(allocationResp == null){
            log.info("住宿分配信息不存在，创建申请表，studentId:{}",studentId);
            return null;
        }
        return AllocationEntity.builder()
                .studentId(allocationResp.getStudentId())
                .roomId(allocationResp.getRoomId())
                .startDate(allocationResp.getStartDate())
                .endDate(allocationResp.getEndDate())
                .price(allocationResp.getPrice())
                .status(AllocationStatusEnumVO.getAllocationStatusEnum(allocationResp.getStatus()))
                .build();
    }

    @Override
    public boolean checkStudentInfo(String studentId) {
        Student student = studentDao.queryStudentInfo(studentId);
        return student != null;
    }

    @Override
    public boolean checkRoomInfo(RoomCheckEntity build) {

        Room roomReq = new Room();
        roomReq.setRoomType(build.getRoomType().getInfo());
        roomReq.setStatus(RoomStatusEnumVO.AVAILABLE.getInfo());
        List<Room> roomList = roomDao.queryRoomInfoListByRoomTypeAndStatus(roomReq);
        if(roomList == null || roomList.isEmpty()){
            return false;
        }
        return true;
    }

    @Override
    public ApplicationResultEntity createApplication(ApplicationCreateEntity applicationCreate) {
        Application application = new Application();
        application.setStudentId(applicationCreate.getStudentId());
        application.setRoomType(applicationCreate.getRoomType().getInfo());
        LocalDate startDate = applicationCreate.getStartDate();
        application.setStartDate(startDate);
        LocalDate endDate = applicationCreate.getEndDate();
        application.setEndDate(endDate);
        application.setStatus(AppliStatusEnumVO.PENDING_APPROVAL.getInfo());
        application.setApplicationId(ApplicationEntity.getRandomApplicationId());
        applicationDao.insert(application);

        Room roomReq = new Room();
        roomReq.setRoomType(applicationCreate.getRoomType().getInfo());
        roomReq.setStatus(RoomStatusEnumVO.AVAILABLE.getInfo());
        List<Room> roomList = roomDao.queryRoomInfoListByRoomTypeAndStatus(roomReq);
        if(roomList == null || roomList.isEmpty()){
            return null;
        }
        Room room = roomList.get(0);
        int minusYears = endDate.getYear() - startDate.getYear();
        int minusMonths = endDate.getMonthValue() - startDate.getMonthValue();
        int months = minusYears * 12 + minusMonths;
        BigDecimal price = room.getPrice().multiply(BigDecimal.valueOf(months));

        allocationDao.insert(Allocation.builder()
                                .studentId(applicationCreate.getStudentId())
                                .roomId(room.getRoomId())
                                .startDate(startDate)
                                .endDate(endDate)
                                .status(AllocationStatusEnumVO.ASSIGNED.getInfo())
                                .price(price)
                                .build());

        return ApplicationResultEntity.builder()
                .applicationId(application.getApplicationId())
                .roomId(room.getRoomId())
                .studentId(application.getStudentId())
                .roomType(RoomTypeEnumVO.getRoomStatusEnumVO(application.getRoomType()))
                .status(AppliStatusEnumVO.getAppliStatusEnum(application.getStatus()))
                .startDate(application.getStartDate())
                .endDate(application.getEndDate())
                .price(price)
                .build();
    }
}
